#pragma once
#include <memory>
#include <future>
#include "DeviceUpgradeUtil.h"

namespace HidDeviceNameSpace{
#define HID_CMD_ROOMS_TAIL_MATCH_REQ 0XFF36
#define HID_CMD_ROOMS_TAIL_MATCH_REP 0XFFB6
#define BIN_STEP 4096
#define AWI_DFU_PRO_RESET_REQ_CODE 0x0001
#define AWI_DFU_PRO_RESET_REP_CODE 0x0081
#define AWI_DFU_PRO_DEVICE_INFO_REQ_CODE  0x0002
#define AWI_DFU_PRO_DEVICE_INFO_REP_CODE  0x0082
#define AWI_DFU_PRO_UPGRADE_START_REQ_CODE 0x0003
#define AWI_DFU_PRO_UPGRADE_START_REP_CODE 0x0083
#define AWI_DFU_PRO_UPGRADE_STOP_REQ_CODE 0x0004
#define AWI_DFU_PRO_UPGRADE_STOP_REP_CODE 0x0084
#define AWI_DFU_PRO_UPGRADE_BIN_START_REQ_CODE 0x0005
#define AWI_DFU_PRO_UPGRADE_BIN_START_REP_CODE 0x0085
#define AWI_DFU_PRO_UPGRADE_BIN_REQ_CODE 0x0006
#define AWI_DFU_PRO_UPGRADE_BIN_REP_CODE 0x0086
#define AWI_DFU_PRO_UNKNOW_CODE 0xFFFF

#define BUFFER_SIZE 1024
}

class HidDevInfo{
public:
    
    bool operator==(const HidDevInfo other){
        return m_product_name == other.m_product_name && m_product_model == other.m_product_model && m_phy_version == other.m_phy_version && m_soft_version == other.m_soft_version && m_serial_number == other.m_serial_number && m_unique_id == other.m_unique_id && mainDevice == other.mainDevice; 
    }

    HidDevInfo(){}
    ~HidDevInfo(){}
    std::string m_product_name;
    std::string m_product_model; 
    std::string m_phy_version; 
    std::string m_soft_version; 
    std::string m_serial_number; 
    std::string m_unique_id;
    bool mainDevice = false;
};

class HidInfo{
public:
    bool m_success_getinfo = false;
    std::vector<HidDevInfo> subDevices;
    HidInfo(){}

    ~HidInfo(){}
};


class HidDevice: public std::enable_shared_from_this<HidDevice>{
public:
    using Ptr = std::shared_ptr<HidDevice>;
    using WeakPtr = std::weak_ptr<HidDevice>;



    HidDevice(const std::string& device_path, std::string& product_model, const std::string& product_name, const std::string& phy_version, 
        const std::string& soft_version, const std::string& serial_number, 
        const std::string& unique_id, std::vector<HidDevInfo> sub_devices);

    HidDevice(){}

    virtual ~HidDevice(){

    }

    bool UpdateDevice(const std::string& device_path, const std::string& product_name, const std::string& phy_version, 
        const std::string& soft_version, const std::string& serial_number, 
        const std::string& unique_id, std::vector<HidDevInfo> sub_devices);

    bool GetDeviceBasicInfo(std::string& product_name, std::string& product_model, std::string& phy_version, 
        std::string& soft_version, std::string& serial_number, 
        std::string& unique_id, std::vector<HidDevInfo>& sub_devices);

    virtual bool Upgrade(const std::string& file_path) = 0;
    
    bool IsUpgrading();
    
    int GetUpgradeProgress();

    bool Reboot();

    bool Reset();

    std::string GetDevicePath(){ return m_device_file_path;}
protected:
    std::string m_device_file_path;
    std::string m_product_name; 
    std::string m_phy_version; 
    std::string m_soft_version; 
    std::string m_serial_number; 
    std::string m_unique_id;
    std::string m_product_model;
    std::shared_ptr<DeviceUpgradeUtil> m_upgrade;
    std::vector<HidDevInfo> m_sub_devices;
    std::mutex m_field_lock;
    bool m_isUpgrading;
};


bool GetDeviceBasicInfo(std::string device_path, std::vector<HidDevInfo>& subDevices);
